온보딩 api 연결#36
Hidden character warning
Conversation
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthrough이 PR은 온보딩 수직 슬라이스를 추가합니다. 네트워크 계층에 Ktorfit/KSP 의존성과 HTTP 클라이언트 로깅을 설정하고, OnboardingService와 관련 요청/응답 모델(AnniversaryRequest, CoupleConnectionRequest, ProfileRequest, InviteCodeResponse, OnBoardingStatusResponse)을 도입했습니다. 데이터 계층에는 DefaultOnboardingRepository와 repositoryModule/dataModule DI 구성이 추가되었고, 도메인 계층에는 InviteCode 값 클래스, OnboardingStatus 열거형 및 OnBoardingRepository 인터페이스와 해당 단위 테스트들이 포함됩니다. 몇몇 .gitkeep 파일이 삭제되었습니다. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| } else { | ||
| LogLevel.NONE | ||
| } | ||
| logger = Logger.ANDROID |
There was a problem hiding this comment.
Logger.ANDROID 그대로 쓰면 될 것 같아요!
| dependencies { | ||
| implementation(libs.bundles.ktor) | ||
| implementation(libs.ktorfit.lib) | ||
| ksp(libs.ktorfit.ksp) |
There was a problem hiding this comment.
이 설정이 있어야 createOnboardingService 처럼 Ktrofit이 서비스 인터페이스 프록시를 만들기 때문에 추가했어 !
single<OnboardingService> {
get<Ktorfit>().createOnboardingService()
}
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@data/src/main/java/com/twix/data/repository/DefaultOnboardingRepository.kt`:
- Around line 8-14: DefaultOnboardingRepository::fetchInviteCode currently lets
network exceptions from OnboardingService bubble up; wrap the call to
service.fetchInviteCode() in a try/catch and convert technical exceptions into a
domain-friendly result (e.g. return a Result<InviteCode, DomainError> or throw a
specific domain exception) so callers (UI) can handle errors consistently;
specifically catch Ktor
ResponseException/ClientRequestException/ServerResponseException (or a generic
Exception as fallback), map them to a DomainError (or Result.failure with mapped
error), and only on success construct and return InviteCode(response.inviteCode)
so the repository surface (DefaultOnboardingRepository, fetchInviteCode,
OnBoardingRepository, InviteCode) exposes domain-level errors instead of raw
HTTP exceptions.
🧹 Nitpick comments (4)
domain/src/test/java/com/twix/domain/model/InviteCodeTest.kt (1)
10-42: 테스트 가독성을 위해 Given-When-Then 구분을 통일해 주세요.
현재는 구조가 생략되어 테스트 의도가 덜 선명합니다. 모든 테스트에 동일한 구분을 두면 유지보수가 쉬워집니다. 코딩 가이드라인에 따라 제안드립니다.🧪 예시 (첫 테스트에 적용)
`@Test` fun `유효한 초대 코드는 정상적으로 생성된다`() { + // given val inviteCode = InviteCode("AB12CD34") + // when + // then assertThat(inviteCode.value).isEqualTo("AB12CD34") }domain/src/test/java/com/twix/domain/model/OnboardingStatusTest.kt (1)
24-28: assertEquals 인자 순서를 관례대로 맞춰주세요.
현재 순서는 실패 메시지에서 expected/actual이 뒤바뀌어 디버깅이 혼란스러울 수 있습니다. 아래처럼 expected → actual 순으로 정리해 주세요.✅ 제안 수정
- assertEquals(result, expected) + assertEquals(expected, result)domain/src/main/java/com/twix/domain/repository/OnBoardingRepository.kt (1)
6-15: 요청 타입을String으로 두면 도메인 의미와 검증이 약해집니다.
왜 문제인가요: 단순 문자열은 필드 의미가 드러나지 않고, 도메인 레벨에서 유효성 검증/불변성 보장이 어려워집니다. 또한 전송 포맷(JSON 등)에 도메인이 끌려갈 수 있습니다.
어떻게 개선할 수 있나요:AnniversarySetupRequest,CoupleConnectionRequest,ProfileSetupRequest같은 도메인 요청 모델(불변 data class)을 정의하고, data 레이어에서 네트워크 DTO로 매핑하는 구조를 권장합니다. 서버 스펙이 정말 “문자열 본문”인지도 확인해보실까요?도메인 모듈 리뷰 가이드에 근거해 제안합니다.
data/src/main/java/com/twix/data/repository/DefaultOnboardingRepository.kt (1)
21-31: request 파라미터가 String 타입으로 되어 있습니다.
anniversarySetup,coupleConnection,profileSetup메서드의 request 파라미터가 모두String타입입니다. 이는 JSON 문자열을 직접 전달하는 방식으로 보입니다.현재 구조가 의도된 것이라면 괜찮지만, 타입 안전성과 유지보수성을 위해 각 요청에 맞는 도메인 모델(예:
AnniversarySetupRequest,CoupleConnectionRequest)을 정의하고 Repository에서 직렬화하는 방식도 고려해 볼 수 있습니다. 이렇게 하면 호출하는 쪽에서 잘못된 형식의 요청을 컴파일 타임에 방지할 수 있습니다.이 부분은 프로젝트의 설계 방향에 따라 결정하시면 됩니다. 현재 단계에서는 API 연결이 주 목적이므로, 추후 리팩토링 시 고려해 주세요.
| class DefaultOnboardingRepository( | ||
| private val service: OnboardingService, | ||
| ) : OnBoardingRepository { | ||
| override suspend fun fetchInviteCode(): InviteCode { | ||
| val response = service.fetchInviteCode() | ||
| return InviteCode(response.inviteCode) | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find other Repository implementations to check error handling patterns
fd -e kt -path '*repository*' -type f | head -20Repository: YAPP-Github/Twix-Android
Length of output: 236
🏁 Script executed:
# Search for error handling patterns in repository classes
rg -n "runCatching|try\s*\{|Result<|catch\s*\(" --type=kotlin -g '*Repository*' -A 2Repository: YAPP-Github/Twix-Android
Length of output: 50
🏁 Script executed:
# Look for domain error model definitions
fd -e kt -type f | xargs grep -l "sealed.*Error\|sealed.*class.*Error\|object.*Error" | head -20Repository: YAPP-Github/Twix-Android
Length of output: 238
🏁 Script executed:
# Check the full DefaultOnboardingRepository implementation
fd -e kt -path '*DefaultOnboardingRepository*' -type fRepository: YAPP-Github/Twix-Android
Length of output: 236
🏁 Script executed:
# Find repository files
find . -name "*Repository.kt" | head -20Repository: YAPP-Github/Twix-Android
Length of output: 218
🏁 Script executed:
# Search for error handling patterns in kotlin files
rg "runCatching|try\s*\{|Result<|catch\s*\(" -A 2 | head -100Repository: YAPP-Github/Twix-Android
Length of output: 50
🏁 Script executed:
# Look for domain error model definitions
rg "sealed.*class|object.*Error|sealed.*Error" --type kotlin | head -30Repository: YAPP-Github/Twix-Android
Length of output: 276
🏁 Script executed:
# Get the full DefaultOnboardingRepository implementation
cat data/src/main/java/com/twix/data/repository/DefaultOnboardingRepository.ktRepository: YAPP-Github/Twix-Android
Length of output: 1067
🏁 Script executed:
# Find all Repository implementations to check patterns
find . -name "*Repository.kt" -not -path "*/build/*" | xargs grep -l "class.*Repository"Repository: YAPP-Github/Twix-Android
Length of output: 144
🏁 Script executed:
# Check the domain repository interface
cat domain/src/main/java/com/twix/domain/repository/OnBoardingRepository.ktRepository: YAPP-Github/Twix-Android
Length of output: 479
🏁 Script executed:
# Search for Result types and error handling utilities
find . -name "*.kt" -not -path "*/build/*" | xargs grep -l "sealed class Result\|Result<" | head -10Repository: YAPP-Github/Twix-Android
Length of output: 50
🏁 Script executed:
# Look for any error/exception models
find . -name "*Error.kt" -o -name "*Exception.kt" | head -20Repository: YAPP-Github/Twix-Android
Length of output: 50
🏁 Script executed:
# Search for OnboardingService implementation
find . -name "*OnboardingService*" -o -name "*Service.kt" | head -20Repository: YAPP-Github/Twix-Android
Length of output: 142
🏁 Script executed:
# Check ViewModel or UseCase error handling
find . -name "*ViewModel.kt" -o -name "*UseCase.kt" | xargs grep -l "try\|catch\|error\|Error" | head -10Repository: YAPP-Github/Twix-Android
Length of output: 50
🏁 Script executed:
# Look at network layer for error handling
find . -path "*network*" -name "*.kt" | xargs grep -l "Exception\|error\|catch" | head -10Repository: YAPP-Github/Twix-Android
Length of output: 50
🏁 Script executed:
# Check if there are any other data layer operations with error handling
find . -path "*data*" -name "*.kt" | xargs grep -n "try\s*\{" | head -30Repository: YAPP-Github/Twix-Android
Length of output: 86
🏁 Script executed:
# Check OnboardingService implementation
cat core/network/src/main/java/com/twix/network/service/OnboardingService.ktRepository: YAPP-Github/Twix-Android
Length of output: 917
🏁 Script executed:
# Search for error handling in data layer more broadly
find . -path "*data*" -name "*.kt" | xargs grep -n "try" | head -30Repository: YAPP-Github/Twix-Android
Length of output: 50
🏁 Script executed:
# Check for error handling in all layers
find . -name "*.kt" -not -path "*/build/*" | xargs grep -n "catch" | head -30Repository: YAPP-Github/Twix-Android
Length of output: 50
🏁 Script executed:
# Look for network error handling or exception handling
find . -path "*network*" -name "*.kt" | xargs cat | head -100Repository: YAPP-Github/Twix-Android
Length of output: 2898
네트워크 예외 처리가 필요합니다.
현재 구현에서 OnboardingService를 통한 네트워크 호출 시 발생하는 예외가 그대로 상위로 전파됩니다. HttpClient가 expectSuccess = true로 설정되어 있기 때문에 4xx, 5xx 상태 코드에서 예외가 발생합니다.
코딩 가이드라인에서 "에러가 도메인 레벨로 적절히 변환되는가?"를 확인하도록 되어 있는데, 현재는 기술 계층의 예외가 도메인 계층으로 올라가고 있습니다.
프로젝트에서 사용 중인 에러 처리 패턴이 있다면 그에 맞춰 적용하면 됩니다. 예를 들어:
- 도메인 레벨의 정의된 예외로 변환
Result<T>또는 유사한 래퍼 타입 사용- 예외별로 구분된 처리 로직
UI 레이어에서 일관되게 에러를 처리하려면 어디서 예외를 캐치하고 도메인 계층으로 변환할 계획인지 논의해 주세요.
🤖 Prompt for AI Agents
In `@data/src/main/java/com/twix/data/repository/DefaultOnboardingRepository.kt`
around lines 8 - 14, DefaultOnboardingRepository::fetchInviteCode currently lets
network exceptions from OnboardingService bubble up; wrap the call to
service.fetchInviteCode() in a try/catch and convert technical exceptions into a
domain-friendly result (e.g. return a Result<InviteCode, DomainError> or throw a
specific domain exception) so callers (UI) can handle errors consistently;
specifically catch Ktor
ResponseException/ClientRequestException/ServerResponseException (or a generic
Exception as fallback), map them to a DomainError (or Result.failure with mapped
error), and only on success construct and return InviteCode(response.inviteCode)
so the repository surface (DefaultOnboardingRepository, fetchInviteCode,
OnBoardingRepository, InviteCode) exposes domain-level errors instead of raw
HTTP exceptions.
| } else { | ||
| LogLevel.NONE | ||
| } | ||
| logger = Logger.ANDROID |
There was a problem hiding this comment.
Logger.ANDROID 그대로 쓰면 될 것 같아요!
| @POST("onboarding/anniversary") | ||
| suspend fun anniversarySetup( | ||
| @Body request: String, | ||
| ) | ||
|
|
||
| @POST("onboarding/couple-connection") | ||
| suspend fun coupleConnection( | ||
| @Body request: String, | ||
| ) | ||
|
|
||
| @POST("onboarding/profile") | ||
| suspend fun profileSetup( | ||
| @Body request: String, | ||
| ) |
| "COUPLE_CONNECTION" -> COUPLE_CONNECTION | ||
| "PROFILE_SETUP" -> PROFILE_SETUP | ||
| "ANNIVERSARY_SETUP" -> ANNIVERSARY_SETUP | ||
| "COMPLETED" -> COMPLETED |
There was a problem hiding this comment.
문자열 하드코딩보다는 trim + uppercase로 비교하는 건 어떠세요?
There was a problem hiding this comment.
오 ! 내가 생각하지 못한 방법인데 좋은 것 같아 👍
리뷰 반영 커밋: 00dd422
| @JvmInline | ||
| value class InviteCode( | ||
| val value: String, | ||
| ) { | ||
| init { | ||
| require(value.length == INVITE_CODE_LENGTH) { INVALID_INVITE_CODE_EXCEPTION } | ||
| require(INVITE_CODE_REGEX.matches(value)) { INVALID_INVITE_CODE_EXCEPTION } | ||
| } | ||
|
|
||
| companion object { | ||
| private val INVITE_CODE_REGEX = Regex("^[A-Z0-9]+$") | ||
| private const val INVITE_CODE_LENGTH = 8 | ||
| private const val INVALID_INVITE_CODE_EXCEPTION = | ||
| "InviteCode must be 8 characters of uppercase letters and digits" | ||
| } | ||
| } |
There was a problem hiding this comment.
커플을 연결할 때 유저가 입력하는 UI 값을 이 클래스로 변환해서 서버로 전송한다고 하면, 잘못된 값을 입력했을 때 require로 인해서 앱이 죽어버릴 수도 있을 거 같거든요. 그래서 유효성 체크하는 부분을 보완하면 좋을 거 같아요.
예를 들면 유효성 검사에 실패했을 때 Result로 래핑해서 BaseViewModel에서 처리하고 경고 메시지를 보여주거나 이런식으로 개선하는 것도 괜찮지 않을까 싶습니다! 다른 방법을 생각하고 계신 게 있으면 말씀해주세요
There was a problem hiding this comment.
앗 이 부분을 미리 말을 못했구나 에러처리 관련한 부분은 우리가 아직 논의가 안돼서 임시로 구현해놨어 ! 😅
나도 현수가 말한 것 처럼 InvalidInviteCodeException같은 특정 에러 상태를 나타내는 클래스를 만들고
이 에러 상태에 따른 적절한 string Resource를 매핑하는 객체를 만들어 처리하는 방법을 사용했었는데,
요건 우리가 추후 에러 처리를 논의할 때 딥하게 논의해보면 좋을 것 같아 !
| .isInstanceOf(IllegalArgumentException::class.java) | ||
| .hasMessage("InviteCode must be 8 characters of uppercase letters and digits") |
There was a problem hiding this comment.
이 부분을 InvalidInviteCodeException이라는 걸 만들어서 관리하는 건 어떠신가요?
| @ParameterizedTest | ||
| @ValueSource( | ||
| strings = [ | ||
| "ABC123", | ||
| "AB12CD345", | ||
| ], | ||
| ) | ||
| fun `8자리가 아닌 초대 코드는 예외가 발생한다`(invalidLengthCode: String) { | ||
| assertThatThrownBy { InviteCode(invalidLengthCode) } | ||
| .isInstanceOf(IllegalArgumentException::class.java) | ||
| .hasMessage("InviteCode must be 8 characters of uppercase letters and digits") | ||
| } |
There was a problem hiding this comment.
InvalidInviteCodeException를 따로 만들면 규칙에 맞지 않는 초대 코드는 예외가 발생한다, 8자리가 아닌 초대 코드는 예외가 발생한다 이 두 테스트를 하나로 묶는 것도 가능할 것 같아요
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In
`@core/network/src/main/java/com/twix/network/model/request/CoupleConnectionReqeust.kt`:
- Line 6: Rename the misspelled data class CoupleConnectionReqeust to
CoupleConnectionRequest and rename the source file from
CoupleConnectionReqeust.kt to CoupleConnectionRequest.kt; update all
references/imports/usages throughout the codebase to use CoupleConnectionRequest
(search for CoupleConnectionReqeust and replace), and ensure any constructors,
serialization names, or tests referencing the old symbol are adjusted to the new
class name.
♻️ Duplicate comments (2)
core/network/src/main/java/com/twix/network/service/OnboardingService.kt (2)
3-3:CoupleConnectionReqeustimport에 오타가 있습니다.해당 클래스의 오타 수정이 완료되면 이 import도 함께 업데이트해주세요.
12-15:anniversarySetup도 다른 엔드포인트처럼 Request DTO를 사용해야 합니다.
coupleConnection과profileSetup은 각각CoupleConnectionReqeust와ProfileRequestDTO를 사용하고 있지만,anniversarySetup은 여전히String을 직접 사용하고 있습니다. Swagger 스펙에 따르면 request body가 JSON 형식이어야 하므로, 문자열을 그대로 보내면 서버와 통신이 제대로 되지 않을 가능성이 높습니다.✏️ 수정 제안
AnniversaryRequestDTO를 생성하고 적용해주세요:// AnniversaryRequest.kt `@Serializable` data class AnniversaryRequest( val anniversary: String, // 또는 서버 스펙에 맞는 필드명 )+import com.twix.network.model.request.AnniversaryRequest + `@POST`("onboarding/anniversary") suspend fun anniversarySetup( - `@Body` request: String, + `@Body` request: AnniversaryRequest, )
| import kotlinx.serialization.Serializable | ||
|
|
||
| @Serializable | ||
| data class CoupleConnectionReqeust( |
There was a problem hiding this comment.
클래스명에 오타가 있습니다: CoupleConnectionReqeust → CoupleConnectionRequest
Reqeust가 아닌 Request로 수정이 필요합니다. 파일명(CoupleConnectionReqeust.kt)도 함께 변경해주세요. 지금 수정하지 않으면 다른 곳에서 이 클래스를 참조하게 되어 나중에 수정 범위가 넓어질 수 있습니다.
✏️ 수정 제안
-data class CoupleConnectionReqeust(
+data class CoupleConnectionRequest(
val inviteCode: String,
)파일명도 CoupleConnectionRequest.kt로 변경해주세요.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| data class CoupleConnectionReqeust( | |
| data class CoupleConnectionRequest( | |
| val inviteCode: String, | |
| ) |
🤖 Prompt for AI Agents
In
`@core/network/src/main/java/com/twix/network/model/request/CoupleConnectionReqeust.kt`
at line 6, Rename the misspelled data class CoupleConnectionReqeust to
CoupleConnectionRequest and rename the source file from
CoupleConnectionReqeust.kt to CoupleConnectionRequest.kt; update all
references/imports/usages throughout the codebase to use CoupleConnectionRequest
(search for CoupleConnectionReqeust and replace), and ensure any constructors,
serialization names, or tests referencing the old symbol are adjusted to the new
class name.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@core/network/src/main/java/com/twix/network/service/OnboardingService.kt`:
- Around line 12-15: The anniversarySetup API currently accepts a raw String;
create a typed request DTO (e.g.,
com.twix.network.model.request.AnniversarySetupRequest annotated with
`@Serializable` containing fields like month: Int, day: Int and any other required
properties) and change OnboardingService.anniversarySetup to accept `@Body`
request: AnniversarySetupRequest instead of String; confirm the exact fields
against the API/back-end spec and add any missing properties and validation
annotations.
♻️ Duplicate comments (1)
data/src/main/java/com/twix/data/repository/DefaultOnboardingRepository.kt (1)
13-16: 네트워크 에러 처리에 대해 (이미 논의됨)이전 리뷰에서 에러 처리가 필요하다는 피드백이 있었고, PR 설명에서 "팀 내 전략이 합의되지 않아 의도적으로 이번 PR에서는 생략"했다고 명시되어 있습니다.
코딩 가이드라인에서 "에러가 도메인 레벨로 적절히 변환되는가?"를 확인하도록 되어 있으니, 추후 에러 처리 전략이 결정되면
runCatching이나Result<T>패턴 등을 통해 도메인 레벨 에러 변환을 구현해 주세요.
🧹 Nitpick comments (1)
data/src/main/java/com/twix/data/repository/DefaultOnboardingRepository.kt (1)
27-33: 파라미터 네이밍 개선을 고려해 보세요.현재
coupleConnection(request: String)과profileSetup(request: String)에서request라는 제네릭한 파라미터명을 사용하고 있습니다. 하지만 실제로는:
coupleConnection:request= 초대 코드profileSetup:request= 닉네임도메인 인터페이스(
OnBoardingRepository)의 시그니처도 함께 고려해야 하지만, 가능하다면inviteCode,nickname처럼 의미가 명확한 파라미터명을 사용하면 코드 가독성이 향상됩니다.// 예시 override suspend fun coupleConnection(inviteCode: String) { service.coupleConnection(CoupleConnectionRequest(inviteCode)) } override suspend fun profileSetup(nickname: String) { service.profileSetup(ProfileRequest(nickname)) }
| @POST("onboarding/anniversary") | ||
| suspend fun anniversarySetup( | ||
| @Body request: String, | ||
| ) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
rg -n "Anniversary" --type=kotlin -g '!**/build/**'Repository: YAPP-Github/Twix-Android
Length of output: 50
🏁 Script executed:
cat core/network/src/main/java/com/twix/network/service/OnboardingService.ktRepository: YAPP-Github/Twix-Android
Length of output: 1057
🏁 Script executed:
# Search for request/response models in the same directory as OnboardingService
fd -e "kt" core/network/src/main/java/com/twix/network/ | head -20Repository: YAPP-Github/Twix-Android
Length of output: 549
🏁 Script executed:
# List all request models to see the pattern
fd -e "Request.kt" core/network/src/main/java/com/twix/network/model/request/Repository: YAPP-Github/Twix-Android
Length of output: 605
🏁 Script executed:
# Check if there's an AnniversarySetupRequest or similar already defined
rg "AnniversarySetup|AnniversaryRequest" --type=kotlinRepository: YAPP-Github/Twix-Android
Length of output: 50
🏁 Script executed:
# Look at some example request DTOs to understand the pattern
cat core/network/src/main/java/com/twix/network/model/request/CoupleConnectionRequest.ktRepository: YAPP-Github/Twix-Android
Length of output: 230
🏁 Script executed:
fd . 'core/network/src/main/java/com/twix/network/model/request/' --extension ktRepository: YAPP-Github/Twix-Android
Length of output: 228
🏁 Script executed:
cat core/network/src/main/java/com/twix/network/model/request/ProfileRequest.ktRepository: YAPP-Github/Twix-Android
Length of output: 219
🏁 Script executed:
# Search for other `@Body` request: String patterns in the codebase
rg "@Body.*String" --type=kotlinRepository: YAPP-Github/Twix-Android
Length of output: 171
anniversarySetup도 전용 Request DTO를 사용해야 합니다.
coupleConnection과 profileSetup은 각각 CoupleConnectionRequest, ProfileRequest 같은 데이터 클래스를 사용하고 있는데, anniversarySetup만 @Body request: String으로 되어 있습니다.
왜 문제가 되나요?
- 타입 안정성 부족: 단순 String으로는 요청 데이터가 무엇인지 명확하지 않습니다
- Swagger 문서화 어려움: DTO가 없으면 API 스펙이 정확하게 생성되지 않습니다
- 일관성 깨짐: 같은 패턴의 엔드포인트들이 다르게 구현되어 유지보수가 어렵습니다
- 직렬화 검증 불가: 데이터 유효성 검증을 위해
@Serializable데코레이터를 적용할 수 없습니다
개선 방법:
AnniversarySetupRequest 데이터 클래스를 만들어서 사용하세요:
// com.twix.network.model.request 패키지에 추가
`@Serializable`
data class AnniversarySetupRequest(
val month: Int,
val day: Int,
// 실제 필요한 필드들...
)
// OnboardingService에서
suspend fun anniversarySetup(
`@Body` request: AnniversarySetupRequest,
)API 문서나 백엔드 스펙을 확인해서 anniversary 엔드포인트가 어떤 필드를 요구하는지 알려주실 수 있나요?
🤖 Prompt for AI Agents
In `@core/network/src/main/java/com/twix/network/service/OnboardingService.kt`
around lines 12 - 15, The anniversarySetup API currently accepts a raw String;
create a typed request DTO (e.g.,
com.twix.network.model.request.AnniversarySetupRequest annotated with
`@Serializable` containing fields like month: Int, day: Int and any other required
properties) and change OnboardingService.anniversarySetup to accept `@Body`
request: AnniversarySetupRequest instead of String; confirm the exact fields
against the API/back-end spec and add any missing properties and validation
annotations.
dogmania
left a comment
There was a problem hiding this comment.
요청 DTO 하나만 더 수정해주세요..! 서버 예외 처리는 나중에 ApiException, DomainError 이런 거 만들어서 래핑하는 식으로 구현하는 건 어떠세요??
| suspend fun anniversarySetup( | ||
| @Body request: String, | ||
| ) |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@data/src/main/java/com/twix/data/repository/DefaultOnboardingRepository.kt`:
- Around line 19-22: DefaultOnboardingRepository.fetchOnboardingStatus currently
calls OnboardingStatus.from(response.status) which can throw
IllegalArgumentException for unknown values; add an UNKNOWN enum constant to
OnboardingStatus and update OnboardingStatus.from(String) to return UNKNOWN for
unrecognized inputs, and also wrap the call in
DefaultOnboardingRepository.fetchOnboardingStatus with runCatching { ...
}.getOrDefault(OnboardingStatus.UNKNOWN) so any unexpected exception still
yields a safe UNKNOWN default; reference OnboardingStatus.from and
DefaultOnboardingRepository.fetchOnboardingStatus when making these changes.
♻️ Duplicate comments (1)
data/src/main/java/com/twix/data/repository/DefaultOnboardingRepository.kt (1)
14-17: 네트워크 예외가 도메인 계층으로 그대로 누수됩니다.
왜 문제가 되나:service.fetchInviteCode()에서 발생하는 예외가 그대로 전파되면 UI에서 일관된 실패 처리가 어렵고 계층 분리가 약해집니다.
어떻게 개선하나: Repository에서 도메인 오류/Result로 변환하거나 공통 매퍼를 적용해 주세요. PR 설명상 보류된 부분인데, 후속 이슈로 처리 계획이 있을까요? As per coding guidelines, ...
| override suspend fun fetchOnboardingStatus(): OnboardingStatus { | ||
| val response = service.fetchOnBoardingStatus() | ||
| return OnboardingStatus.from(response.status) | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
fd -type f -name "*.kt" | xargs rg "class OnboardingStatus|sealed class OnboardingStatus|enum class OnboardingStatus" -lRepository: YAPP-Github/Twix-Android
Length of output: 385
🏁 Script executed:
fd -type f -name "*OnboardingStatus*"Repository: YAPP-Github/Twix-Android
Length of output: 238
🏁 Script executed:
rg -n "OnboardingStatus" data/ --type kt -l | head -20Repository: YAPP-Github/Twix-Android
Length of output: 94
🏁 Script executed:
cat -n domain/src/main/java/com/twix/domain/model/OnboardingStatus.ktRepository: YAPP-Github/Twix-Android
Length of output: 699
🏁 Script executed:
cat -n domain/src/main/java/com/twix/domain/model/OnboardingStatusTest.ktRepository: YAPP-Github/Twix-Android
Length of output: 166
🏁 Script executed:
cat -n data/src/main/java/com/twix/data/repository/DefaultOnboardingRepository.ktRepository: YAPP-Github/Twix-Android
Length of output: 1545
OnboardingStatus.from()의 미정의 값 처리를 개선해 주세요.
왜 문제가 되나: OnboardingStatus.from()은 알 수 없는 상태값을 받으면 IllegalArgumentException을 던지는데, 현재 Repository에서 이를 catch하지 않아 미처리 예외로 인한 앱 크래시가 발생합니다.
어떻게 개선하나:
OnboardingStatusenum에UNKNOWN값을 추가하고from()이 이를 반환하도록 변경, 또는- Repository에서
runCatching으로 감싸서 예외를 catch하고 안전한 기본값으로 처리
어느 방식이 더 적절할까요? 서버로부터 예상치 못한 상태값이 올 수 있는 상황에서는 Unknown 상태를 명시적으로 처리하는 것이 권장됩니다.
🤖 Prompt for AI Agents
In `@data/src/main/java/com/twix/data/repository/DefaultOnboardingRepository.kt`
around lines 19 - 22, DefaultOnboardingRepository.fetchOnboardingStatus
currently calls OnboardingStatus.from(response.status) which can throw
IllegalArgumentException for unknown values; add an UNKNOWN enum constant to
OnboardingStatus and update OnboardingStatus.from(String) to return UNKNOWN for
unrecognized inputs, and also wrap the call in
DefaultOnboardingRepository.fetchOnboardingStatus with runCatching { ...
}.getOrDefault(OnboardingStatus.UNKNOWN) so any unexpected exception still
yields a safe UNKNOWN default; reference OnboardingStatus.from and
DefaultOnboardingRepository.fetchOnboardingStatus when making these changes.
chanho0908
left a comment
There was a problem hiding this comment.
현수 말대로 ApiException, DomainException으로 분리하는거 좋은 아이디어인 것 같아 !
일전에 모든 에러를 하나로 통일해 처리하니까 두 에러를 분리해야할 때 너무 복잡했었거든
예를 들어 에러 메시지를 모두 스낵바로 출력한다고 가정했을 때
닉네임 유효성 검사 같은 에러는 따로 분리하는 과정이 필요했거든
당시엔 더 나은 방법을 찾지 못했는데 현수 말대로 두 에러를 분리하면 해결할 수 있을 것 같아 ! 🤔
| suspend fun anniversarySetup( | ||
| @Body request: String, | ||
| ) |

이슈 번호
#34
리뷰/머지 희망 기한 (선택)
2026.01.24
작업내용
온보딩 API 연동 완료
실제 UI 연동은 로그인/토큰 저장 기능 구현 완료된 뒤에 토큰을 담아서 구현 예정 !
결과물
리뷰어에게 추가로 요구하는 사항 (선택)
OnBoardingStatus, InviteCode 유효성 검증 관련 비즈니스 로직을 캡슐화하고 테스트 코드까지 추가했어 !
아직 구체적인 네트워크 호출 에러처리를 협의하지 않아서 에러처리는 제외하고 구현했고
요건 같이 이야기 해보면 좋을 것 같아서 해커톤 때 이야기해보자 😃